<APIs: cl-waffe>
!normal
!normal
(dims &optional (mean 2.0) (stddev 1.0))
REPL:
CL-WAFFE> (!normal `(10 10)) :mean 2.0 :stddev 1.0
#Const(((0.939... 1.594... ~ 3.769... 2.525...)
...
(2.022... 2.286... ~ 0.844... 3.609...)) :dtype :float :shape (10 10) :backward NIL)
!randn
!randn
(dims)
REPL:
CL-WAFFE> (!randn `(10 10))
#Const(((-0.20... -0.17... ~ -0.82... 0.113...)
...
(-1.33... -0.45... ~ 0.163... 2.218...)) :dtype :float :shape (10 10) :backward NIL)
!uniform-random
!uniform-random
(dims &key (limit 1))
Initializes tensor with sampling uniform random.
The returned tensor is filled by random numbers 0<=x<limit
REPL:
CL-WAFFE> (!uniform-random `(10 10) :limit 2.0)
#Const(((0.290... 1.492... ~ 1.814... 0.777...)
...
(0.194... 1.930... ~ 1.669... 1.442...)) :dtype :float :shape (10 10) :backward NIL)
!beta
!beta
(dims alpha beta)
Initializes the new tensor of dims with sampling beta distribution.
Algorithm: https://dl.acm.org/doi/pdf/10.1145/359460.359482
REPL:
CL-WAFFE> (!beta `(10 10) 5.0 1.0)
#Const(((0.917... 0.964... ~ 0.927... 0.807...)
...
(0.876... 0.777... ~ 0.902... 0.466...)) :dtype :float :shape (10 10) :backward NIL)
!gamma
!gamma
(dims k &optional (theta 1.0))
REPL:
CL-WAFFE> (!gamma `(10 10) 1.0)
#Const(((2.338... 1.112... ~ 0.845... 0.096...)
...
(0.185... 0.081... ~ 0.041... 2.381...)) :dtype :float :shape (10 10) :backward NIL)
!chisquare
!chisquare
(dims df)
REPL:
CL-WAFFE> (!chisquare `(10 10) 2.0)
#Const(((0.228... 1.644... ~ 3.603... 1.272...)
...
(8.122... 0.070... ~ 3.789... 0.322...)) :dtype :float :shape (10 10) :backward NIL)
!bernoulli
!bernoulli
(dims rate)
REPL:
CL-WAFFE> (!bernoulli `(10 10) 0.5)
#Const(((1.0 1.0 ~ 1.0 0.0)
...
(0.0 0.0 ~ 1.0 1.0)) :dtype :float :shape (10 10) :backward NIL)
!binomial
!binomial
(dims rate)
REPL:
CL-WAFFE> (!binomial `(10 10) 0.5)
#Const(((0.0 0.0 ~ 0.0 0.0)
...
(1.0 1.0 ~ 0.0 0.0)) :dtype :float :shape (10 10) :backward NIL)
!random-with
!random-with
(dims f)
Initializes the tensor of dims. Each element is initialized with f
, f is a funcallable function. and called with the index of the tensor.
See also: !init-with which is alias for !random-with.
REPL:
CL-WAFFE> (!random-with '(10 10) #'(lambda (n) n))
#Const(((0.0 1.0 ~ 8.0 9.0)
...
(90.0 91.0 ~ 98.0 99.0)) :dtype :float :shape (10 10) :backward NIL)
!random
!random
(dims limit)
REPL:
CL-WAFFE> (!random `(10 10) 1.0)
#Const(((0.569... 0.154... ~ 0.840... 0.956...)
...
(0.344... 0.495... ~ 0.212... 0.374...)) :dtype :float :shape (10 10) :backward NIL)
CL-WAFFE> (!random `(10 10) 3)
#Const(((2.0 1.0 ~ 0.0 2.0)
...
(2.0 2.0 ~ 1.0 0.0)) :dtype :float :shape (10 10) :backward NIL)
CL-WAFFE> (!random `(10 10) `(1.0 2.0))
#Const(((1.642... 1.500... ~ 1.848... 1.415...)
...
(1.032... 1.951... ~ 1.362... 1.905...)) :dtype :float :shape (10 10) :backward NIL)
CL-WAFFE> (!random `(10 10) `(1 5))
#Const(((2.0 2.0 ~ 4.0 4.0)
...
(1.0 3.0 ~ 2.0 3.0)) :dtype :float :shape (10 10) :backward NIL)
!zeros-like
!zeros-like
(tensor)
Return a const where the shape is the same as tensor but elements are zero.
Example:
(setq a (!randn `(10 10)))
(!zeros-like a)
;#Const(((0.0 0.0 ~ 0.0 0.0)
; ...
; (0.0 0.0 ~ 0.0 0.0)) :mgl t :shape (10 10))
!ones-like
!ones-like
(tensor)
(setq a (!randn `(10 10)))
(!ones-like a)
;#Const(((1.0 1.0 ~ 1.0 1.0)
; ...
; (1.0 1.0 ~ 1.0 1.0)) :mgl t :shape (10 10))
!full-like
!full-like
(tensor element)
element
.
Example:
(setq a (!randn `(10 10)))
(!full-like a 3)
;#Const(((3.0 3.0 ~ 3.0 3.0)
; ...
; (3.0 3.0 ~ 3.0 3.0)) :mgl t :shape (10 10))
!zeros
!zeros
(shape)
Initializing constant tensor with given shape, where initial elements are zero.
Input: shape (cons)
Output: Tensor (which is constant)
Example:
(!zeros `(10 10))
;#Const(((0.0 0.0 ~ 0.0 0.0)
; ...
; (0.0 0.0 ~ 0.0 0.0)) :mgl t :shape (10 10))
!ones
!ones
(shape)
The same as !zeros but initial element is one.
Example:
(!ones `(10 10))
;#Const(((1.0 1.0 ~ 1.0 1.0)
; ...
; (1.0 1.0 ~ 1.0 1.0)) :mgl t :shape (10 10))
!fill
!fill
(shape element)
The same as !zeros, !ones but initial element is given element.
Note: the argument element
coerced into mgl-mat:*default-mat-ctype*
Example:
(!fill '(10 10) 10)
;#Const(((10.0 10.0 ~ 10.0 10.0)
; ...
; (10.0 10.0 ~ 10.0 10.0)) :mgl t :shape (10 10))
!shape
!shape
(tensor &optional (nth nil))
Returns the shape of tensor when nth=nil.nth
indicates the index of shape, !shape return specified value.
Example:
(setq a (!randn `(10 10 10)))
(!shape a) ; => (10 10 10)
(!shape a 0) ;=> 10
!dims
!dims
(tensor)
Returns the total length of a given tensor's dims
Example:
(!dims (!zeros '(10 10 10))) ; => 3
!size
!size
(tensor)
Returns the total size of a tensor
Example:
(!size (!zeros '(10 10 10))) ; => 1000
WaffeTensor
waffetensor
Option | Value |
Constructor: | (sysconst value &key (backend *default-backend*) (extend nil) (thread-data nil) (path-through-node? nil) (no-jit nil) (breakme? nil) &aux (data (init-waffe-tensor-data value)) (backend (check-backend backend extend)) (grad nil) (thread-data thread-data) (destructive? t) (is-next-destruct? breakme?) (is-sysconst? t) (force-ignore-jit no-jit) (path-through-node? path-through-node?) (is-mat (typep value (quote mat))) (grad-tmp (make-grad-tmp))) |
Predicate: | waffetensor-p |
Copier: | copy-waffetensor |
Print Function: | (lambda (tensor stream depth) (declare (ignore depth)) (format stream (render-tensor tensor))) |
An structure of Waffe's Tensor. This structure have:
- data (type of WaffeTensorContentType)
- the computation node for backprops, and grads
- backend informations and parameters for optimizing.
There's three ways to make it.
- (const value)
- Constant tensor, grad won't be created.
- (tensor value)
- Parameter tensor, grad will be created.
- (sysconst value)
- Constant tensor where tensor sometime cached. Users don't have to use this.
Value is following:
- simple-array
- mgl-mat:mat (recommended)
- fixnum
- float
- null
- cons
- function (for lazy evaluation)
- ratio (when make, coerced to float)
This structure is printable and printed nicely.
data
Option Value Type: cl-waffe::waffetensortypes
Read Only: nil
Accessor: cl-waffe::waffetensor-data
Initform: nil
grad-tmp
Option Value Type: cl-waffe::grad-tmp
Read Only: nil
Accessor: cl-waffe::waffetensor-grad-tmp
Initform: (cl-waffe::make-grad-tmp)
backward
Option Value Type: boolean
Read Only: nil
Accessor: cl-waffe::waffetensor-backward
Initform: nil
backend
Option Value Type: keyword
Read Only: nil
Accessor: cl-waffe::waffetensor-backend
Initform: :mgl
grad
Option Value Type: cl-waffe::waffetensortypes
Read Only: nil
Accessor: cl-waffe::waffetensor-grad
Initform: nil
variables
Option Value Type: list
Read Only: nil
Accessor: cl-waffe::waffetensor-variables
Initform: nil
state
Option Value Type: t
Read Only: nil
Accessor: cl-waffe::waffetensor-state
is-mat
Option Value Type: boolean
Read Only: nil
Accessor: cl-waffe::waffetensor-is-mat
Initform: nil
is-param?
Option Value Type: boolean
Read Only: nil
Accessor: cl-waffe::waffetensor-is-param?
Initform: nil
is-ancestor-param
Option Value Type: boolean
Read Only: nil
Accessor: cl-waffe::waffetensor-is-ancestor-param
Initform: nil
is-next-destruct?
Option Value Type: boolean
Read Only: nil
Accessor: cl-waffe:waffetensor-is-next-destruct?
Initform: nil
destructive?
Option Value Type: boolean
Read Only: nil
Accessor: cl-waffe:waffetensor-destructive?
Initform: nil
thread-data
Option Value Type: (or cl-waffe::waffenodethread null)
Read Only: nil
Accessor: cl-waffe:waffetensor-thread-data
Initform: nil
is-sysconst?
Option Value Type: boolean
Read Only: nil
Accessor: cl-waffe::waffetensor-is-sysconst?
Initform: nil
path-through-node?
Option Value Type: boolean
Read Only: nil
Accessor: cl-waffe::waffetensor-path-through-node?
Initform: nil
tensor-ident
Option Value Type: (or null symbol)
Read Only: nil
Accessor: cl-waffe::waffetensor-tensor-ident
Initform: nil
force-ignore-jit
Option Value Type: boolean
Read Only: nil
Accessor: cl-waffe::waffetensor-force-ignore-jit
Initform: nil
key
Option Value Type: (or null cons)
Read Only: nil
Accessor: cl-waffe::waffetensor-key
Initform: nil
idx
Option Value Type: (or null symbol)
Read Only: nil
Accessor: cl-waffe::waffetensor-idx
Initform: nil
is-data-destructed?
Option Value Type: boolean
Read Only: nil
Accessor: cl-waffe:waffetensor-is-data-destructed?
Initform: nil
parameter
parameter
(tensor)
Redefining new-tensor where old-tensor is const or tensor.
The new-tensor can made grads.
Excepted usage is like:
(setq my-param (parameter (!mul 0.01 (!randn `(10 10)))))
Note that: tensor's computation node that old-tensor has, will be lost. Only tensor's data and backend will be extended.
- Input
- Tensor (as usual, defined by (const)(sysconst)(tensor))
- Output
- Tensor (as usual, defined by (tensor))
data
data
(tensor)
Access tensor's data. This won't be copied.
When tensor's data is lazy evaluted, this function behave following:
- When tensor is transposed and lazy evaluted, directly returns function object for speed.
- When tensor is cached and lazy evaluted, returns mat object.
- Input
- WaffeTensor
- Output
- mgl-mat:mat, or waffetensorcontentdata
when (data tensor) is a function and is:
- cached mat
- Return mgl-mat, this do not make copy
- lazy-evaluation or transposed
- Return function itself
Note: this function is setfable and inlined
value
value
(tensor &key (ignore-transpose nil))
Access tensor's data, but if tensor is lazy-evaluated, eval them.
Note: this is not setfable
backward
backward
(tensor)
Compute back propagation by traversing the Tensor's computation node.
The parameters of the model defined by (tensor) or to which (Parameter tensor) is applied, store the gradient in grad slot.
Note that: tensor must be the shape of `(1) or single value. Otherwise an error occurs.
In the process calculating backward, new backwards won't be created. (*no-grad* automatically becomes t)
- Input
- WaffeTensor
- Output
- NIL
with-no-grad
with-no-grad
(&body body)
(with-no-grad
(call (model) x))
*no-grad*
*no-grad*
!add
!add
(x y)
Adds x and y.
In the case when x or y is not a tensor, automatically creates a new tensor.
Destructive mode: (!!add x y)
It supports:
- Broadcasting shapes
- JIT
Examples
(setq a (!randn `(3 3)))
(setq b (!randn `(3 3)))
(setq c (!randn `(3 1)))
(!add 1 1)
;=> Const(2)
(!add (const 1)(const 1))
;=> Const(2)
(!add a b)
;#Const(((3.418... 1.974... 0.177...)
; ...
; (-1.30... 0.987... 1.917...)) :mgl t :shape (3 3))
(!add a c)
;#Const(((1.426... 2.129... 1.050...)
; ...
; (-0.64... 0.269... 0.303...)) :mgl t :shape (3 3))
!!add
!!add
(target-x y)
Adds target-x and y in a destructive way.
target-x is always substituted for the result
y is not subject to side effects unless target-x is not a mat.
See also: Destructive Operations
!sub
!sub
(x y)
Subtract x by y.
In the case when x or y is not a tensor, automatically creates a new tensor.
It supports:
- Broadcasting shapes
- JIT
Examples
(setq a (!randn `(3 3)))
(setq b (!randn `(3 3)))
(setq c (!randn `(3 1)))
(!sub 1 1)
;=> Const(0)
(!sub (const 1)(const 1))
;=> Const(0)
(!sub a b)
;#Const(((-0.86... 1.413... 1.139...)
; ...
; (0.017... -0.44... -1.31...)) :mgl t :shape (3 3))
(!sub a c)
;#Const(((1.128... 1.258... 0.267...)
; ...
; (-0.64... 0.269... 0.303...)) :mgl t :shape (3 3))
!!sub
!!sub
(target-x y)
Substracts target-x by y in a destructive way.
target-x is always substituted for the result.
y is not subject to side effects unless target-x is not a mat.
See also: Destructive Operations
!mul
!mul
(x y)
Multiply x and y with element-wise.
In the case when x or y is not a tensor, automatically creates a new tensor.
It supports:
- Broadcasting shapes
- JIT
Examples
(setq a (!randn `(3 3)))
(setq b (!randn `(3 3)))
(setq c (!randn `(3 1)))
(!mul 1 1)
;=> Const(1)
(!mul (const 1)(const 1))
;=> Const(1)
(!mul a b)
;#Const(((2.734... 0.475... -0.31...)
; ...
; (0.426... 0.193... 0.490...)) :mgl t :shape (3 3))
(!mul a c)
;#Const(((2.734... 0.475... -0.31...)
; ...
; (0.426... 0.193... 0.490...)) :mgl t :shape (3 3))
!!mul
!!mul
(target-x y)
Multiplys target-x and y in a destructive way.
target-x is always substituted for the result
y is not subject to side effects unless target-x is not a mat.
See also: Destructive Operations
!div
!div
(x y)
Divides x by y.
In the case when x or y is not a tensor, automatically creates a new tensor.
It supports:
- Broadcasting shapes
- JIT
Examples
(setq a (!randn `(3 3)))
(setq b (!ones `(3 3)))
(setq c (!ones `(3 1)))
(!div 2 1)
;=> Const(2)
(!div (const 2)(const 1))
;=> Const(2)
(!div a b)
;#Const(((1.734... 0.475... -0.31...)
; ...
; (0.426... 0.193... 0.490...)) :mgl t :shape (3 3))
(!div a c)
;#Const(((2.734... 0.475... -0.31...)
; ...
; (0.426... 0.193... 0.490...)) :mgl t :shape (3 3))
!sum
!sum
(x &optional (axis nil) (keepdims nil))
Sum up x where x is a cl-waffe tensor.
For nd tensors...
- 1D
- unsqueeze x with 1, and call !sum again.
- 2D and more.
- Sum up all elements of X
arguments
- axis
- a dimension to reduce
- keepdims
- When t, the returning tensor is repeated with
axis
Example
(setq a (!randn `(10)))
(!sum a)
;=>#Const(4.74653)
(setq a (!randn `(10 10)))
(!sum a)
;=>#Const(1.5428619)
(!sum a 0)
;=>#Const(((-2.07... 0.463... ~ 1.778... 1.695...)) :mgl t :shape (1 10))
(!sum a 1)
;#Const(((0.967...)
; ...
; (2.774...)) :mgl t :shape (10 1))
(!sum a 0 t)
;#Const(((-2.07... 0.463... ~ 1.778... 1.695...)
; ...
; (-2.07... 0.463... ~ 1.778... 1.695...)) :mgl t :shape (10 10))
!mean
!mean
(x &optional (axis nil) (keepdims nil))
Example
(setq a (!ones '(10 10)))
;#Const(((1.0 1.0 ~ 1.0 1.0)
; ...
; (1.0 1.0 ~ 1.0 1.0)) :mgl t :shape (10 10))
(!mean a)
;=>Const(1.0)
!dot
!dot
(x y)
Computes the dot product of x and y where x and y are 1d Tensor.
🗒Note: Unlike Numpy's dot, !dot only supports for 1d tensors with the same number of elements and the tensor of which dims is larger than 1, regarded as 1d tensors.
Example
(setq a (!randn `(10)))
(setq b (!randn `(10)))
(!dot a b)
;=> #Const(1.0842022e-19)
!matmul
!matmul
(x y)
Multiplying matrices x
and y
.
!matmul has many behaviours depends on the dimensionality of the tensors as follows:
- x and y are 1D
- The dot-product is returned.
(setq a (!randn `(10))) (setq b (!randn `(10))) (!matmul a b) ;=>#Const(-2.0)
- x and y are both 2D
- The matrix-matrix product is returned.
(setq a (!randn `(3 10))) (setq b (!randn `(10 3))) (!matmul a b) ;#Const(((2.309... 2.223... 3.630...) ; ... ; (2.334... 2.850... 3.678...)) :mgl t :shape (3 3))
- x is 2D and y is 3D.
- The matrix and y's each matrix are multiplied and is returned.
(setq a (!randn `(3 10))) (setq b (!randn `(5 10 3))) (!matmul a b) ;(!aref b 0) ~ (!aref b 4) is multiplied with a ;#Const((((3.257... 2.731... 1.670...) ; ... ; (2.523... 2.251... 1.276...)) ; ... ; ((2.610... 2.764... 2.415...) ; ... ; (2.080... 2.204... 1.751...))) :mgl t :shape (5 3 3))
- x is 3D and y is 2D.
- The matrix and x's each matrix are multiplied and is returned.
(setq a (!randn `(5 3 10))) (setq b (!randn `(10 3))) (!matmul a b) ;(!aref a 0) ~ (!aref a 4) is multiplied with b ;#Const((((2.309... 2.204... 1.556...) ; ... ; (3.746... 3.869... 3.091...)) ; ... ; ((3.260... 3.200... 2.847...) ; ... ; (3.008... 2.186... 2.376...))) :mgl t :shape (5 3 3))
- x is 3D and y is 3D.
- The Batch Filtered Matrix-Matrix product is returned.
(setq a (!randn `(5 3 10))) (setq b (!randn `(5 10 3))) ; The returned mat is comprised of: ; (!matmul (!aref a 0)(!aref b 0)) ; (!matmul (!aref a 1)(!aref b 1)) ; (!matmul (!aref a 2)(!aref b 2)) ; (!matmul (!aref a 3)(!aref b 3)) (!matmul a b) ;#Const((((6.621... -5.61... 2.898...) ; ... ; (-2.96... -4.26... -3.99...)) ; ... ; ((-0.02... 2.707... 5.989...) ; ... ; (-3.35... 3.561... -3.90...))) :mgl t :shape (5 3 3))
- Otherwise
- Currently not implemented. In the near future for more will be added.
!sin
!sin
(x)
Example
(setq a (!randn `(5)))
;=>#Const((0.638... 0.527... 0.515... 0.495... 0.912...) :mgl t :shape (5))
(!sin a)
;=>#Const((-0.44... -0.64... -0.66... -0.70... -0.09...) :mgl t :shape (5))
!cos
!cos
(x)
Example
(setq a (!randn `(5)))
;=>#Const((0.638... 0.527... 0.515... 0.495... 0.912...) :mgl t :shape (5))
(!cos a)
;=>#Const((0.803... 0.864... 0.870... 0.879... 0.611...) :mgl t :shape (5))
!tan
!tan
(x)
Example
(setq a (!randn `(5)))
;=>#Const((0.638... 0.527... 0.515... 0.495... 0.912...) :mgl t :shape (5))
(!tan a)
;=>#Const((0.741... 0.582... 0.566... 0.540... 1.293...) :mgl t :shape (5))
!asin
!asin
(x)
!acos
!acos
(x)
!atan
!atan
(x)
!sinh
!sinh
(x)
Example
(setq a (!randn `(5)))
;=>#Const((0.638... 0.527... 0.515... 0.495... 0.912...) :mgl t :shape (5))
(!sinh a)
;=>#Const((0.682... 0.551... 0.538... 0.516... 1.044...) :mgl t :shape (5))
!cosh
!cosh
(x)
Example
(setq a (!randn `(5)))
;=>#Const((0.638... 0.527... 0.515... 0.495... 0.912...) :mgl t :shape (5))
(!cosh a)
;=>#Const((1.210... 1.142... 1.135... 1.125... 1.446...) :mgl t :shape (5))
!tanh
!tanh
(x)
!asinh
!asinh
(x)
!acosh
!acosh
(x)
!atanh
!atanh
(x)
!abs
!abs
(x)
Computes the absolute value of each element in x
.
Example:
(setq a (!random `(10 10) '(-1.0 1.0)))
;#Const(((0.048... 0.805... ~ 0.769... 0.252...)
; ...
; (0.159... -0.66... ~ -0.55... -0.23...)) :mgl t :shape (10 10))
(!abs a)
;#Const(((0.048... 0.805... ~ 0.769... 0.252...)
; ...
; (0.159... 0.667... ~ 0.553... 0.239...)) :mgl t :shape (10 10))
!log
!log
(x)
Returns a new tensor with the natural logarithm of the elements of input.
yi = log(e xi)
Example
(setq a (!ones '(10 10)))
(!log a)
;#Const(((0.0 0.0 ~ 0.0 0.0)
; ...
; (0.0 0.0 ~ 0.0 0.0)) :mgl t :shape (10 10))
!exp
!exp
(x)
Example
(setq a (!randn `(10 10)))
;#Const(((0.624... 0.807... ~ 0.500... 0.937...)
; ...
; (0.662... 0.299... ~ 0.761... 0.729...)) :mgl t :shape (10 10))
(!exp a)
;#Const(((1.866... 2.242... ~ 1.650... 2.553...)
; ...
; (1.939... 1.349... ~ 2.140... 2.073...)) :mgl t :shape (10 10))
!pow
!pow
(x n)
x
with n, returning a new sysconst.Example
(setq a (!ones `(10 10)))
(!pow a 3)
;#Const(((1.0 1.0 ~ 1.0 1.0)
; ...
; (1.0 1.0 ~ 1.0 1.0)) :mgl t :shape (10 10))
!sqrt
!sqrt
(x)
x
with 1/2, creating new sysconst and nodes.Example
(setq a (!ones `(10 10)))
(!sqrt a 3)
;#Const(((1.0 1.0 ~ 1.0 1.0)
; ...
; (1.0 1.0 ~ 1.0 1.0)) :mgl t :shape (10 10))
!argmax
!argmax
(tensor &key (dim -1) (keepdims nil) (max nil))
Returns the indices of the maximum value of all elements in the input tensor.
If max=t, retures the maximun value of dim.
- dim
- The dimension to reduce. If nil, the argmax of the flattened input is returned.
- keepdims
- whether the output tensor has dim retained or not. Ignored if dim=-1
Example
(setq a (!randn `(5)))
;#Const((0.933... 0.158... 0.822... 0.881... 0.831...) :mgl t :shape (5))
(!argmax a)
;#Const((0.0) :mgl t :shape (1))
(setq a (!randn `(10 10 10)))
;#Const((((0.393... 0.658... ~ 0.003... 0.609...)
; ...
; (0.394... 0.252... ~ 0.688... 0.057...))
; ...
; ((0.325... 0.794... ~ 0.540... 0.381...)
; ...
; (0.310... 0.035... ~ 0.280... 0.431...))) :mgl t :shape (10 10 10))
(!argmax a :dim 2)
;#Const(((5.0 9.0 ~ 0.0 4.0)
; ...
; (2.0 0.0 ~ 2.0 5.0)) :mgl t :shape (10 10))
(!argmax a :dim 2 :keepdims t)
;#Const((((5.0 5.0 ~ 5.0 5.0)
; ...
; (4.0 4.0 ~ 4.0 4.0))
; ...
; ((2.0 2.0 ~ 2.0 2.0)
; ...
; (5.0 5.0 ~ 5.0 5.0))) :mgl t :shape (10 10 10))
!argmin
!argmin
(tensor &key (dim -1) (keepdims nil) (min nil))
Returns the indices of the minimum value of all elements in the input tensor.
If min=t, argmin returns the minimum value of dim.
- dim
- The dimension to reduce. If nil, the argmax of the flattened input is returned.
- keepdims
- whether the output tensor has dim retained or not. Ignored if dim=-1.
Example
(setq a (!randn `(5)))
;=>#Const((0.635... 0.101... 0.864... 0.563... 0.481...) :mgl t :shape (5))
(!argmin a)
;=>#Const((1.0) :mgl t :shape (1))
(setq a (!randn `(10 10 10)))
;#Const((((0.267... 0.113... ~ 0.142... 0.208...)
; ...
; (0.174... 0.948... ~ 0.232... 0.462...))
; ...
; ((0.454... 0.361... ~ 0.605... 0.731...)
; ...
; (0.099... 0.816... ~ 0.729... 0.996...))) :mgl t :shape (10 10 10))
(!argmin a)
;#Const((415.0...) :mgl t :shape (1))
!squeeze
!squeeze
(x &optional (dim nil))
Returns a new tensor with a dimension of size one removed at the specified position.
When dim=nil or -1, the last position of dim will be removed.
If the specified position of a tensor isn't one, !squeeze is skipped.
Example
(setq a (!randn `(10 1 10)))
;#Const((((0.928... 0.556... ~ 0.697... 0.973...))
; ...
; ((0.368... 0.995... ~ 0.589... 0.716...))) :mgl t :shape (10 1 10))
(!squeeze a 1)
;#Const(((0.928... 0.556... ~ 0.697... 0.973...)
; ...
; (0.368... 0.995... ~ 0.589... 0.716...)) :mgl t :shape (10 10))
(!squeeze a -1)
;#Const((((0.928... 0.556... ~ 0.697... 0.973...))
; ...
; ((0.368... 0.995... ~ 0.589... 0.716...))) :mgl t :shape (10 1 10))
(setq a (!randn `(10 10 1)))
;#Const(((0.991... 0.248... ~ 0.610... 0.289...)
; ...
; (0.593... 0.177... ~ 0.374... 0.668...)) :mgl t :shape (10 10))
!unsqueeze
!unsqueeze
(x &optional (dim 0) (count 1))
Returns a new tensor with a dimension of size one inserted at the specified position.
dim indicates the position, when dim=-1, it indicates a last dimension of x
.
Example
(setq a (!randn `(10 10)))
;#Const(((0.685... 0.827... ~ 0.076... 0.102...)
; ...
; (0.802... 0.571... ~ 0.207... 0.283...)) :mgl t :shape (10 10))
(!unsqueeze a)
;#Const((((0.685... 0.827... ~ 0.076... 0.102...)
; ...
; (0.802... 0.571... ~ 0.207... 0.283...))) :mgl t :shape (1 10 10))
(!unsqueeze a -1)
;#Const((((0.685...)
; ...
; (0.102...))
; ...
; ((0.802...)
; ...
; (0.283...))) :mgl t :shape (10 10 1))
(!unsqueeze a 2)
;#Const(((0.685... 0.827... ~ 0.076... 0.102...)
; ...
; (0.802... 0.571... ~ 0.207... 0.283...)) :mgl t :shape (10 10 1 1))
!reshape
!reshape
(x dim)
Return a new sysconst with changing its shape. x won't be modified.
If dims has the element of t
, t is automatically inferred from the remaining dimensions and the number of elements in dim. (count t dim) must be 1 (Todo: Fix).
The total size of tensor must not be changed before or after the call to reshape.
See also: nil
Example
(setq a (!randn `(10 10 10)))
(!reshape a '(1 10 100))
;#Const((((0.454... 0.277... ~ 0.536... 0.135...)
; ...
; (0.857... 0.714... ~ 0.169... 0.279...))) :mgl t :shape (1 10 100))
(!reshape a '(1 1 t))
;#Const((((0.454... 0.277... ~ 0.169... 0.279...))) :mgl t :shape (1 1 1000))
!repeats
!repeats
(x axis repeats)
Repeats x
along specified axis
by repeats
, creating new sysconst.
x can be: mat or tensor.
Example
(setq a (!randn '(1 3 3)))
;#Const((((0.333... 0.914... 0.260...)
; ...
; (0.611... 0.110... 0.113...))) :mgl t :shape (1 3 3))
(!repeats a 0 3)
;#Const((((0.333... 0.914... 0.260...)
; ...
; (0.611... 0.110... 0.113...))
; ...
; ((0.333... 0.914... 0.260...)
; ...
; (0.611... 0.110... 0.113...))) :mgl t :shape (3 3 3))
(!repeats (const 10.0) 3 10)
;#Const(((((10.0 10.0 ~ 10.0 10.0)))) :mgl t :shape (1 1 1 10))
!flatten
!flatten
(tensor)
Flattens input by reshaping it into a one-dimensional tensor.
The operation is the same as (!reshape tensor '(t))
Example:
(setq a (!randn `(10 10)))
;#Const(((0.688... 0.580... ~ 0.013... 0.461...)
; ...
; (0.214... 0.248... ~ 0.540... 0.416...)) :mgl t :shape (10 10))
(!flatten a)
;#Const((0.688... 0.580... ~ 0.540... 0.416...) :mgl t :shape (100))
!transpose
!transpose
(x &optional result)
Transpose x where x is a 2d tensor.
Transposed x is lazy evaluated until called by !matmul.
Todo: implement 3d, 4d version...
Example
(setq a (!randn `(3 5)))
(setq a (!transpose a))
;#Const(#<FUNCTION (LABELS CL-WAFFE.BACKENDS.MGL::LAZYTRANSPOSE :IN CL-WAFFE.BACKENDS.MGL::LAZY-EVAL-TRANSPOSE) {10038CBADB}>)
(!matmul a (!randn '(3 5)))
;#Const(((0.653... 0.400... 0.471... 0.705... 0.623...)
; ...
; (1.220... 0.760... 0.975... 1.360... 1.029...)) :mgl t :shape (5 5))
!transpose1
!transpose1
(x &rest result)
Transpose x but doesn't produce lazy-eval.
Todo: Numcl's operation couldm't optimized well. i need to reimplement it by myself.
Example
(setq a (!randn `(10 5 3)))
(!transpose1 a)
;#Const((((-0.47... -0.03... ~ -0.17... 0.328...)
; ...
; (0.210... -1.80... ~ 1.648... 0.135...))
; ...
; ((-0.52... 1.509... ~ 0.643... 0.258...)
; ...
; (-0.26... -1.14... ~ -1.08... 1.126...))) :mgl t :shape (3 5 10))
!concatenate
!concatenate
(axis &rest tensors)
tensors
in the given axis
. All tensors must have the same shape.Example
(setq a (!randn `(3 3 3)))
;#Const((((1.000... -0.00... -0.25...)
; ...
; (1.473... -0.44... 1.680...))
; ...
; ((0.569... 0.852... 0.405...)
; ...
; (0.024... 0.756... 0.383...))) :mgl t :shape (3 3 3))
(!concatenate 0 a a a)
;#Const((((1.000... -0.00... -0.25...)
; ...
; (1.473... -0.44... 1.680...))
; ...
; ((0.569... 0.852... 0.405...)
; ...
; (0.024... 0.756... 0.383...))) :mgl t :shape (9 3 3))
(mgl-mat:M= (data (!aref * '(0 3)))
(data (!aref * '(3 6))))
;T
!stack
!stack
(axis &rest tensors)
Stacks the given tensors
in the specified axis
.
Internally, !stack adds 1 to the specified axis before calling !concatenate.
Note: Currently, when unsqueezing given tensors, !stack creates copies every time in order to prevent side effects. To avoid this, !concatenate is recommended to use. (TO FIX)
Example
(setq a (!randn `(2 2 2)))
;#Const((((-0.83... -1.74...)
; (0.119... 0.162...))
; ((-1.81... 0.907...)
; (-0.50... -0.96...))) :mgl t :shape (2 2 2))
(!stack 0 a a a)
;#Const(((((-0.83... -1.74...)
; (0.119... 0.162...))
; ((-1.81... 0.907...)
; (-0.50... -0.96...)))
; ...
; (((-0.83... -1.74...)
; (0.119... 0.162...))
; ((-1.81... 0.907...)
; (-0.50... -0.96...)))) :mgl t :shape (3 2 2 2))
(mgl-mat:M= (data (!aref * 0))(data (!aref * 1)))
; T
!split
!split
(tensor split-size &key (axis 0))
Splits the tensor into chunks in the specified axis
. Each chunk is a copy of original tensor.
split-size indicates the strides of each chunk, that is, tensor
will be split into equalliy size of split-size
.
split-size must be fixnum.rr
Alternatively, !aref, (setf !aref) is available.
Example
(setq a (!randn `(4 2 2)))
;#Const((((-0.48... -1.22...)
; (0.251... 0.476...))
; ...
; ((-0.66... 1.045...)
; (-0.44... 1.592...))) :mgl t :shape (4 2 2))
(!split a 2)
;(#Const((((-0.48... -1.22...)
; (0.251... 0.476...))
; ((0.864... -0.93...)
; (-0.43... 0.346...))) :mgl t :shape (2 2 2))
; #Const((((-1.91... -0.63...)
; (-0.08... 0.867...))
; ((-0.66... 1.045...)
; (-0.44... 1.592...))) :mgl t :shape (2 2 2)))
; the rests are filled with 0.0
(!split a 3)
;(#Const((((-0.48... -1.22...)
; (0.251... 0.476...))
; ...
; ((-1.91... -0.63...)
; (-0.08... 0.867...))) :mgl t :shape (3 2 2))
; #Const((((-0.66... 1.045...)
; (-0.44... 1.592...))
; ...
; ((0.0 0.0)
; (0.0 0.0))) :mgl t :shape (3 2 2)))
!hstack
!hstack
(&rest tensors)
!vstack
!vstack
(&rest tensors)
!aref
!aref
(tensor &rest dims)
!aref creates a new tensor from the area specified by dims
from the given tensor
.
This function is setfable and both function produces the computation nodes.
dims is consisted of list, and each dimension is described as follow formats:
- t
- t means (0~max-len) in the dimension.
- fixnum
- copies the index of fixnum in the dimension.
- list
- list must be of (start stop), copying tensors from start to stop in the dimension. that is, the result in the dimension is the copy of: start<=x<stop.
Using t as
stop
means: t is the last element in the dimension.
The fixnum used in dims
is not only positive numbers but also negative numbers.
For example, -1 is interpreted as (+ maxlen -1), -2 is interpreted as (+ maxlen -2)...
Note: (setf !aref) overwrites the given tensor's mat but won't overwrites its computation node. in order to update nodes, you must write it like: (setq a (setf (!aref a ...) ...))... See Example for the details.
Tensor cut-outs act on:
- When is not setf
- act on the given tensor.
- When is setf
- act on the target tensor. (e.g.: (setf (!aref target-tensor ...) input-tensor))
Example:
(setq a (!randn `(10 5 3)))
;#Const((((0.621... -1.15... 2.396...)
; ...
; (0.157... 0.389... 1.084...))
; ...
; ((1.123... -0.58... -0.28...)
; ...
; (0.506... -0.44... -0.26...))) :mgl t :shape (10 5 3))
(!aref a '(0 3)) ; interpreted as (!aref a '(0 3) t t)
;#Const((((0.621... -1.15... 2.396...)
; ...
; (0.157... 0.389... 1.084...))
; ...
; ((0.694... 0.954... 1.210...)
; ...
; (0.884... 0.059... 0.190...))) :mgl t :shape (3 5 3))
(!aref a '(1 3))
;#Const((((0.657... 0.834... -2.01...)
; ...
; (1.194... 0.517... 0.356...))
; ((0.694... 0.954... 1.210...)
; ...
; (0.884... 0.059... 0.190...))) :mgl t :shape (2 5 3))
(!aref a '(1 0)) ; When (cdr dims) <= 0, interpreted as (- (!shape tensor dim)(cdr dims))
; In this Example, this is the same as (!aref a '(1 10))
;#Const((((0.657... 0.834... -2.01...)
; ...
; (1.194... 0.517... 0.356...))
; ...
; ((1.123... -0.58... -0.28...)
; ...
; (0.506... -0.44... -0.26...))) :mgl t :shape (9 5 3))
(!aref a '(1 -1))
;#Const((((0.657... 0.834... -2.01...)
; ...
; (1.194... 0.517... 0.356...))
; ...
; ((-2.29... -1.12... -0.68...)
; ...
; (-1.74... 0.489... 1.519...))) :mgl t :shape (8 5 3))
(!aref a t '(0 2))
;Tensors in lower dimensions can also be clipped.
;If 0th dim isn't needed to be cut, place t.
;#Const((((0.621... -1.15... 2.396...)
; (0.642... 0.029... 1.334...))
; ...
; ((1.123... -0.58... -0.28...)
; (-2.43... -0.29... 0.882...))) :mgl t :shape (10 2 3))
(!aref a '(0 2) '(1 2) '(1 3))
;#Const((((0.029... 1.334...))
; ((-1.41... -0.32...))) :mgl t :shape (2 1 2))
; This function is setfable, but currently I won't come up with the best solution to update computation node.
; I know it is very ugly but additional setq is required after setf.
; Also, note that (setf !aref). overwrites a.
(setq a (setf (!aref a '(0 3) '(0 3))(!zeros '(3 3))))
;#Const((((0.0 0.0 0.0)
; ...
; (0.157... 0.389... 1.084...))
; ...
; ((1.123... -0.58... -0.28...)
; ...
; (0.506... -0.44... -0.26...))) :mgl t :shape (10 5 3))
(!aref a 0 0)
;#Const((((0.0 0.0 0.0))) :mgl t :shape (1 1 3))
!where
!where
(condition tensor then else)
Return a tensor of elements selected from either x or y, depending on condition.condition
is given as a lambda expression, which called with an value of (aref tensor index).
!where defined asout = if (condition(tensor[i]), then, else)
Return: A tensor of shape that equal to the condition.
Example
(setq a (!random `(10 10) '(-1.0 1.0)))
;#Const(((0.042... -0.36... ~ 0.250... 0.967...)
; ...
; (-0.21... 0.962... ~ -0.32... 0.215...)) :mgl t :shape (10 10))
(!where #'(lambda (x)(> x 0)) a 1.0 0.0)
;#Const(((1.0 0.0 ~ 1.0 1.0)
; ...
; (0.0 1.0 ~ 0.0 1.0)) :mgl t :shape (10 10))
; works as ReLU
(!mul a (!where #'(lambda (x)(> x 0)) a 1.0 0.0))
;#Const(((0.042... 0.0... ~ 0.250... 0.967...)
; ...
; (0.0... 0.962... ~ 0.0... 0.215...)) :mgl t :shape (10 10))
!index
!index
nil
!filter
!filter
(tensor lambda)
lambda
, it returns an tensor which comprised of the lambda
's returned values.- tensor
- an tensor that to be refered to
- lambda
- an function that returns elements at position
x
(setq tensor (!randn `(10 10)))
(!filter tensor #'(lambda (x)(if (> x 0) x 1.0)))
;#Const(((0.802... 1.331... ~ 0.998... 1.994...)
; ...
; (1.0 0.005... ~ 0.296... 0.358...)) :mgl t :shape (10 10))
!arange
!arange
(&rest args)
Like numpy's arange, arange can be called with a varying number of positional arguments:
(!arange stop)
(!arange 10)
;#Const((0.0 1.0 ~ 8.0 9.0) :mgl t :shape (10))
(!arange start stop)
(!arange 3 10)
;=>#Const((3.0 4.0 ~ 8.0 9.0) :mgl t :shape (7))
(!arange start stop step)
(!arange 3 10 2)
;#Const((3.0 5.0 7.0 9.0) :mgl t :shape (4))
!relu
!relu
(x)
Applying relu to x, return a new sysconst with making nodes.
Relu(x) = { 0 (x < 0), x (x > 0) }
Input: x where x is waffe supported data type.
Output: Tensor
!sigmoid
!sigmoid
(x)
Applyong sigmoid to x, return a new sysconst with making nodes.
Input: x where x is waffe supported data type.
Output: Tensor
!gelu
!gelu
(x &key (approximate t))
Applying gelu to x, returning a new sysconst.
Paper: https://arxiv.org/abs/1606.08415.
TOOD: Improve its performance
GeLU(x) = x * s(x)
When approximate is t:
s(x) = x/2 * [1 + tanh(sqrt(2/pi * (x + 0.044715 * x^3)))]
When is nil:
Not implemented (TODO)
(setq x (!randn `(10 10)))
(!gelu x)
;#Const(((0.201... 0.038... ~ 0.158... 0.040...)
; ...
; (0.300... 1.395... ~ 0.030... 0.029...)) :mgl t :shape (10 10))
!leakey-relu
!leakey-relu
(x &optional (alpha 0.01))
Applying Leakey-relu to x, returning a new sysconst.
Leakey-ReLU is defined as out = {alpha (x < 0), x (x >= 0)}
Example:
(setq x (!randn `(10 10)))
#Const(((0.635... -0.56... ~ -1.15... -1.50...)
...
(0.775... 1.258... ~ -1.29... 0.240...)) :mgl t :shape (10 10))
(!leakey-relu x)
#Const(((0.635... 0.003... ~ 0.013... 0.022...)
...
(0.775... 1.258... ~ 0.016... 0.240...)) :mgl t :shape (10 10))
!swish
!swish
(x &key (beta (const 1.0)))
Applying swish to each element of x
Swish is defined as out = (/ 1 (+ 1 (exp (* beta -1 x))))
In default beta is 1.0, if you want to use trainable one, Swish
is available as a waffe model.
Note that beta must begin given as a waffetensor.
(setq x (!randn `(10 10)))
#Const(((0.635... -0.56... ~ -1.15... -1.50...)
...
(0.775... 1.258... ~ -1.29... 0.240...)) :mgl t :shape (10 10))
(!swish x)
;#Const(((0.415... -0.20... ~ -0.27... -0.27...)
; ...
; (0.531... 0.980... ~ -0.27... 0.134...)) :mgl t :shape (10 10))
(call (Swish :beta 1.0) x) ; its beta is trainable by backpropgating.
;#Const(((0.415... -0.20... ~ -0.27... -0.27...)
; ...
; (0.531... 0.980... ~ -0.27... 0.134...)) :mgl t :shape (10 10))
!softmax
!softmax
(x &key (avoid-overflow t))
Applying softmax to x. !softmax has three behaviours depending on the number of dimensions.
The number of dims is...
- 1
- Softmax is applied to dim=0
(setq a (!randn `(10))) (!softmax a) ;#Const((0.910... 0.886... ~ 0.802... 0.616...) :mgl t :shape (10))
- 2
- Softmax is applied to dim=0
(setq a (!randn `(10 10))) ;#Const(((-0.29... -1.99... ~ -0.36... 1.725...) ; ... ; (0.695... -0.94... ~ 1.179... 0.655...)) :mgl t :shape (10 10)) (!softmax a) ;#Const(((0.064... 0.011... ~ 0.060... 0.489...) ; ... ; (0.129... 0.024... ~ 0.209... 0.124...)) :mgl t :shape (10 10))
- 3
- Softmax is applied to dim=0
(setq a (!randn `(10 10 10))) ;#Const((((2.585... 0.517... ~ 0.428... 0.059...) ; ... ; (-2.11... 0.308... ~ -0.91... 0.649...)) ; ... ; ((-0.75... 1.030... ~ 0.656... -0.00...) ; ... ; (-0.37... -0.52... ~ 1.589... -0.10...))) :mgl t :shape (10 10 10)) (!softmax a) ;#Const((((0.374... 0.047... ~ 0.043... 0.029...) ; ... ; (0.010... 0.115... ~ 0.033... 0.162...)) ; ... ; ((0.029... 0.172... ~ 0.118... 0.061...) ; ... ; (0.048... 0.041... ~ 0.345... 0.063...))) :mgl t :shape (10 10 10))
- 4
- Todo: currently, it returns error.
with-verbose
with-verbose
(&body body)
with-dtype
with-dtype
(dtype &body body)
dtypecase
dtypecase
(&rest cases)
define-with-typevar
define-with-typevar
(function-name type-specifier (&rest args) &body body &aux (fnames (map (quote list) (function (lambda (p) (symb function-name p))) *dtype-prefixes*)) (params (get-params args)))
with-backend
with-backend
(backend &body body)
Switches a backend.
See also: define-node-extension
define-node-extension
define-node-extension
(name &key optimize backend (disassemble-forward nil) forward-declaim forward (disassemble-backward nil) backward-declaim backward)
Adds a new backend to the defined node.
The type of backend is managed by keywords. The backend defined in defnode is always :mgl.
Defined backends can be switched by the macro (with-backend backend)
.
As long as *restart-non-exist-backend* is t, when a computation node reaches a backend that is not defined, :mgl is called, otherwise the condition backend-doesnt-exists will occurs.
Example:
(define-node-extension cl-waffe::AddTensor
:backend :test-backend
:forward ((x y)
(const (+ 1 1)))
:backward ((dy)
(list dy dy)))
(with-backend :mgl
(print (!add 10 10))) ;=> Const(20)
(with-backend :test-backend
(print (!add 10 10))) ;=> Const(2)
(with-backend :hogehoge
(print (!add 10 10))) ; => Const(20)
(let ((*restart-non-exist-backend* nil))
(with-backend :hogehoge
(print (!add 10 10)))) ;=> Evaluation aborted on #<CL-WAFFE::BACKEND-DOESNT-EXISTS {100FA18C43}>.
*restart-non-exist-backend*
*restart-non-exist-backend*
!allow-destruct
!allow-destruct
(tensor)
Tensors which path through this macro are allowed to be destructed by cl-waffe's kernel.
In default, cl-waffe's operators won't make side effects.
(setq a (!randn `(3 3)))
;#Const(((0.811... -0.43... -0.91...)
; ...
; (0.959... -0.62... 1.150...)) :mgl t :shape (3 3))
(!exp a)
;#Const(((2.252... 0.645... 0.400...)
; ...
; (2.610... 0.534... 3.159...)) :mgl t :shape (3 3))
(print a)
;#Const(((0.811... -0.43... -0.91...)
; ...
; (0.959... -0.62... 1.150...)) :mgl t :shape (3 3))
However, This macro let kernel know that the given tensor is allowed to destruct(i.e.: the result is overwritten)
(setq a (!randn `(3 3)))
;#Const(((0.811... -0.43... -0.91...)
; ...
; (0.959... -0.62... 1.150...)) :mgl t :shape (3 3))
(!allow-destruct a)
; T
(!exp a)
;#Const(((2.252... 0.645... 0.400...)
; ...
; (2.610... 0.534... 3.159...)) :mgl t :shape (3 3))
(print a) ; You can see the result is overwritten.
;#Const(((2.252... 0.645... 0.400...)
; ...
; (2.610... 0.534... 3.159...)) :mgl t :shape (3 3))
Avoiding copy, destructive operations are superior in terms of memory usage.
(setq a (!randn `(100 100)))
(time (!exp a))
;Evaluation took:
; 0.000 seconds of real time
; 0.000275 seconds of total run time (0.000219 user, 0.000056 system)
; 100.00% CPU
; 498,150 processor cycles
; 31,264 bytes consed
(!allow-destruct a)
(time (!exp a))
; Evaluation took:
; 0.000 seconds of real time
; 0.000178 seconds of total run time (0.000160 user, 0.000018 system)
; 100.00% CPU
; 273,646 processor cycles
; 0 bytes consed
See also: !disallow-destruct which does the opposite.
!disallow-destruct
!disallow-destruct
(tensor)
(setq a (!randn `(3 3)))
;#Const(((1.084... -1.10... 1.406...)
; ...
; (1.044... 0.059... -0.53...)) :mgl t :shape (3 3))
(!allow-destruct a)
; T
(!disallow-destruct a)
; NIL
(!exp a)
;#Const(((2.957... 0.329... 4.080...)
; ...
; (2.840... 1.060... 0.584...)) :mgl t :shape (3 3))
(print a) ; a is kept remained.
;#Const(((1.084... -1.10... 1.406...)
; ...
; (1.044... 0.059... -0.53...)) :mgl t :shape (3 3))
defnode
defnode
(name initializer-arguments &key parameters (disassemble-forward nil) forward-declaim forward (disassemble-backward nil) backward-declaim backward (document An node, defined by cl-waffe.))
Defines computation nodes in a format that cl-waffe can handle.
Note: the data structures that can be used in arguments, and returned values, must be following:
- WaffeTensor
- 1D list which each element is WaffeTensor
Be aware that you can't use (values x y ...).
- name
- The node's name. constructor and structure are being defined named after this argument.
- initializer-argument
- arguments the constructor have.
- parameter
- The parameters this node has being initializer with initializer-argument.
- disassemble-forward
- when t, when this node is compiled, display the disassemble of forward slot.
- forward-declaim
- Describe the declaim for the forward function. Note that the first argument is a structure. and :forward keyword in this declaim will be replaced by the forward function's name.
- forward
- the definition of forward
- disassemble-backward
- when t, when this node is compiled, display the disassemble of backward slot.
- backward-declaim
- Describe the declaim for the backward function. Note that the first argument is a structure. and :backward keyword in this declaim will be replaced by the backward function's name.
- backward
- the definition of backward
defmodel
defmodel
(name initializer-arguments &key (parameters nil) (disassemble-forward nil) forward-declaim forward (document An model, defined by cl-waffe))
This macro defines a cl-waffe model as name
.
At the same time, a constructor name
is defined and you can initialize your model like:
(cl-waffe.nn:LinearLayer 100 20) ; => [Model: Linearlayer]
- name
- Your model and constructor name
- args
- The arguments of a constructor
- parameters
The parameters your model has.
Every time you initialize the model, the parameters are initialized.
Note that
defmodel
behaves like class.The arguments are the same as
defstruct
Format Example: ((param-name param-initial-value &key (type your-type)))
- forward
Define here the forward propagation of your model.
When backward, Automatic differentiation applies.
defoptimizer
defoptimizer
(name initializer-arguments &key parameters (disassemble-update nil) update-declaim update (document An optimizer, defined by cl-waffe.))
Defines optimizer in the format that cl-waffe can handle.
- Name
- The optimizer's structure and constructor will be defined after name
- Args
- Initializer of the optimizer. The first value of initializer is the hash-table that collected model's parameter where the key is fixnum from 0 to n. You have to store it.
- parameters
- An parameters that it has.
- update
- when training and (update) is called, this slot is called and you optimizer your parameters.
- optimize
- when t, the :update slot is defined with (optimize (speed 3)(space 0)(debug 0)) Default: nil
- document
- docstring for optimizers. You can use string or (with-usage) macro
Example:
;defoptimizer's args must start with params (symbol-name doesn't matter) which receives hash-table whose key is 1..n
(defoptimizer SGD (params &key (lr 1e-3))
:optimize t
:parameters ((params params :type hash-table)
(lr lr :type single-float))
:update (()
(dotimes (i (hash-table-count (self params)))
; W(n+1) = W(n) - n * grad
(!modify (gethash i (self params))) :+=
(!mul (self lr)(grad (gethash i (self params)))))))
;(call (SGD (find-variables model))) will works as update.
;(call-backward (SGD)) will works as zero-grads.
call
call
(model &rest inputs &aux (features (model-inlineable-p model)))
call-backward
call-backward
(model &rest inputs)
self
self
(name)
save-for-backward
save-for-backward
(slot tensor)
get-forward-caller
get-forward-caller
(model)
get-backward-caller
get-backward-caller
(model)
with-calling-layers
with-calling-layers
(input &rest layers)
This macro allows to sequentially call layers.
the argument input
must be a tensor.
Refering each layers from (self) macro, destructively modifying x with the returned value.
Note: This macro supposes models to be returned a single tensor, not a list.
(defmodel MLP (activation)
:parameters ((layer1 (denselayer (* 28 28) 512 T activation))
(layer2 (denselayer 512 256 T activation))
(layer3 (linearlayer 256 10 T)))
:forward ((x)
(with-calling-layers x
(layer1 x)
(layer2 x)
(layer3 x))))
For the different arguments.
(with-calling-layers x
(layer1 x 1 1)
(layer2 1 x 2)
(layer3 x y))
Output: An last value of layers.
deftrainer
deftrainer
(name args &key model optimizer optimizer-args step-model predict (document An trainer structure defined by cl-waffe.))
Defining trainer, which is made in order to call train
function.
The slots you defined can be invoked by using (step-model model &rest args)
, (predict model &rest args)
. See below.
- model
- An model defined by
(defmodel)
which you want to train. - optimizer
- An optimizer defined by
(defoptimizer)
- optimizer-args
- An arguments for optimizer
- step-model
- For each batch step, :step-model is called in
(train)
function. Describe here forward step, backward, zero-grad, update for training. - predict
- an code for predicting
These macro below are defined by macrolet
and you can use them in :step-model, :predict
- (self name)
- access trainer's parameters.
- (model)
- access trainer's model, defined by :model keyword.
- (zero-grad)
- Find model's all parameters and constants, and initialize their grads. (i.e. call optimizer's backward)
- (update)
- Find model's all parameters, and call optimizer and change parameter's data. (i.e. call optimizer's forward)
This trainer macro is defined in order to integrate following works:
- calling models
- calling criterions
- calling backward
- calling optimizer
- calling zero-grad
- defining predict
Example:
(deftrainer MLPTrainer (activation lr)
:model (MLP activation)
:optimizer cl-waffe.optimizers:Adam ; Note: :optimizer requires a single variable.
:optimizer-args (:lr lr) ; these arguments directly expanded to optimizer's args.
:step-model ((x y)
(zero-grad) ; call zero-grad
(let ((out (cl-waffe.nn:softmax-cross-entropy (call (model) x) y))) ; get criterion
(backward out) ; backward
(update) ; call optimizer
out)) ; return loss
:predict ((x)(call (model) x))) ;for predict
(setq trainer (MLPTrainer :relu 1e-4)) ; init your trainer
; Train: (step-model trainer model-input-x model-input-y)
; Predict: (predict trainer model-input-x)
step-model
step-model
(trainer &rest args)
An function for calling trainer object defined by deftrainer By using this function, trainer's step-model will be invoked.
Input: Trainer, Args
predict
predict
(trainer &rest args)
model
model
nil
update
update
(&rest args)
zero-grad
zero-grad
nil
defdataset
defdataset
(name args &key parameters next length (document An dataset structure defined by cl-waffe.))
Defining dataset. (This is kinda pytorch's dataloader)
The slots you defined can be invoked by using (get-dataset dataset index)(get-length dataset).
- parameters
- parameters datasets have.
- next
- when function (get-dataset dataset index) is called, this slot invokes. Return waffetensor for the next batch in response to your task.
- length
- In this form, the function must return the total length of your datasets where the value is fixnum. (Not a batch, and not a current index.)
(defdataset Mnistdata (train valid batch-size)
:parameters ((train train)(valid valid)(batch-size batch-size))
:next ((index)
(list (!set-batch (self train) index (self batch-size))
(!set-batch (self valid) index (self batch-size))))
:length (()(car (!shape (self train)))))
cl-waffe excepts index to be 1, 2, 3, ... (dataset-maxlen)
So, please manage batch-sizes in args and :next slots.
get-dataset
get-dataset
(dataset index)
get-dataset-length
get-dataset-length
(dataset)
model-list
model-list
.mlist
mlist
(&rest models)
mth
mth
(index mlist)
grad
grad
(tensor)
Accessing tensor's grad.
When tensor's grad is nil, an error occurs
- Input
- WaffeTensor
- Output
- An tensor's grad which is the type of mgl-mat:mat or waffetensorcontettype
Note: grad is not setfable